{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pip install --user cvxopt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "from IPython.core.interactiveshell import InteractiveShell\n",
    "InteractiveShell.ast_node_interactivity = \"all\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here we are importing Construct_Rebalance_portfolio.ipynb file as we are using some of its data."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%matplotlib inline\n",
    "import numpy as np  \n",
    "import matplotlib.pyplot as plt  \n",
    "import cvxopt as opt  \n",
    "from cvxopt import blas, solvers  \n",
    "import pandas as pd\n",
    "import pymysql\n",
    "import import_ipynb\n",
    "import sqlalchemy\n",
    "from sqlalchemy import create_engine\n",
    "import S2_Construct_Rebalance_Portfolio\n",
    "\n",
    "np.random.seed(123)\n",
    "\n",
    "# Turn off progress printing  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Below, we are taking the portfolio stocks from the construct_Rebalance_portfolio.ipynb file, and we will take their annual returns from the table for the optimization. We are assigning the weights on historical annual returns of the portfolio stocks."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\Sudip\\Anaconda3\\lib\\site-packages\\ipykernel_launcher.py:25: FutureWarning: Comparing Series of datetimes with 'datetime.date'.  Currently, the\n",
      "'datetime.date' is coerced to a datetime. In the future pandas will\n",
      "not coerce, and a TypeError will be raised. To retain the current\n",
      "behavior, convert the 'datetime.date' to a datetime with\n",
      "'pd.Timestamp'.\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>STOCK_TIKR</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>AIR</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>BSET</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>CBT</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>CPS</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>DCO</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  STOCK_TIKR\n",
       "2        AIR\n",
       "5       BSET\n",
       "6        CBT\n",
       "7        CPS\n",
       "9        DCO"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# We will look past 5-years returns for optimizatin\n",
    "\n",
    "import pyodbc\n",
    "from sqlalchemy import create_engine\n",
    "from datetime import datetime\n",
    "from datetime import date\n",
    "import datetime\n",
    "\n",
    "\n",
    "engine = create_engine('mysql+pymysql://nativeuser:password@localhost/automatic_portfolio_creation')\n",
    "query_ann_ret = \"SELECT * FROM hist_annual_change\"\n",
    "\n",
    "curr_year = date.today().year \n",
    "ref_year = date.today().year - 4\n",
    "start_date = datetime.date(ref_year,12,31)\n",
    "end_date = datetime.date(curr_year,12,31)\n",
    "dfval = S2_Construct_Rebalance_Portfolio.dflookup.copy()\n",
    "dfval.rename(columns = {'symbol':'STOCK_TIKR'}, inplace = True)\n",
    "#dfval.head()\n",
    "\n",
    "dfannRet =pd.read_sql(query_ann_ret,engine)\n",
    "dfannRet['Close'] = dfannRet['Close']*100\n",
    "dfannRet['Close'] = dfannRet['Close'].round(4)\n",
    "dfannRet['Date'] = pd.to_datetime(dfannRet['Date'])\n",
    "dtFilter = (dfannRet['Date'] > start_date) & (dfannRet['Date'] <= end_date)\n",
    "dfannRet = dfannRet.loc[dtFilter]\n",
    "#dfannRet.head(10)\n",
    "\n",
    "dfvalopti = pd.merge(dfannRet,dfval,on='STOCK_TIKR')\n",
    "dfvalopti = dfvalopti.groupby(['STOCK_TIKR']).mean().reset_index()\n",
    "dfvalopti = dfvalopti[(dfvalopti['Close'] > 10) & (dfvalopti['Close'] < 25)]\n",
    "dfvalopti.rename(columns = {'Close':'Annual_Ret'}, inplace = True)\n",
    "dfvalopti = dfvalopti[['STOCK_TIKR']]\n",
    "dfvalopti.head()\n",
    "#dfvalopti.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\Sudip\\Anaconda3\\lib\\site-packages\\ipykernel_launcher.py:17: FutureWarning: Comparing Series of datetimes with 'datetime.date'.  Currently, the\n",
      "'datetime.date' is coerced to a datetime. In the future pandas will\n",
      "not coerce, and a TypeError will be raised. To retain the current\n",
      "behavior, convert the 'datetime.date' to a datetime with\n",
      "'pd.Timestamp'.\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>STOCK_TIKR</th>\n",
       "      <th>Date</th>\n",
       "      <th>Annual_Ret</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>AIR</td>\n",
       "      <td>2015-12-31</td>\n",
       "      <td>-5.3636</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>AIR</td>\n",
       "      <td>2016-12-31</td>\n",
       "      <td>25.7132</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>AIR</td>\n",
       "      <td>2017-12-31</td>\n",
       "      <td>18.8805</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>AIR</td>\n",
       "      <td>2018-12-31</td>\n",
       "      <td>12.0641</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>BSET</td>\n",
       "      <td>2015-12-31</td>\n",
       "      <td>28.5495</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  STOCK_TIKR       Date  Annual_Ret\n",
       "0        AIR 2015-12-31     -5.3636\n",
       "1        AIR 2016-12-31     25.7132\n",
       "2        AIR 2017-12-31     18.8805\n",
       "3        AIR 2018-12-31     12.0641\n",
       "4       BSET 2015-12-31     28.5495"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "[[-5.3636, 25.7132, 18.8805, 12.0641],\n",
       " [28.5495, 21.2121, 23.6842, -13.5638],\n",
       " [-6.7943, 23.6301, 21.8639, -10.8134],\n",
       " [34.0532, 33.2388, 18.4949, -0.2939],\n",
       " [-35.8386, 57.5832, 11.3067, 4.3234],\n",
       " [6.4301, -17.8742, 56.3492, -4.3733],\n",
       " [-22.0886, 24.6235, 27.4924, 7.109],\n",
       " [-5.3086, 27.2781, 30.0703, 3.3712],\n",
       " [-28.9084, 114.5735, -58.4208, -2.9216],\n",
       " [-22.4708, 19.5107, 44.8819, -17.029],\n",
       " [-44.6541, 42.0455, 14.6667, -5.2326],\n",
       " [-4.3254, 4.4133, 21.6495, 7.2034],\n",
       " [-12.7481, 82.6336, -16.162, -13.2987],\n",
       " [-12.5372, 78.0855, -9.9591, -20.7576],\n",
       " [-31.044, 36.5231, 11.5894, -5.1261],\n",
       " [33.0257, 15.6572, 31.4364, -8.6839],\n",
       " [-14.841, 34.4398, 28.0864, -12.0482]]"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\n",
    "engine = create_engine('mysql+pymysql://nativeuser:password@localhost/automatic_portfolio_creation')\n",
    "query_ann_ret = \"SELECT * FROM hist_annual_change\"\n",
    "\n",
    "curr_year = date.today().year \n",
    "ref_year = date.today().year - 5\n",
    "start_date = datetime.date(ref_year,12,31)\n",
    "end_date = datetime.date(curr_year,12,31)\n",
    "dfval = dfvalopti.copy()\n",
    "#dfval.rename(columns = {'symbol':'STOCK_TIKR'}, inplace = True)\n",
    "#dfval.head()\n",
    "\n",
    "dfannRet =pd.read_sql(query_ann_ret,engine)\n",
    "dfannRet['Close'] = dfannRet['Close']*100\n",
    "dfannRet['Close'] = dfannRet['Close'].round(4)\n",
    "dfannRet['Date'] = pd.to_datetime(dfannRet['Date'])\n",
    "dtFilter = (dfannRet['Date'] > start_date) & (dfannRet['Date'] <= end_date)\n",
    "dfannRet = dfannRet.loc[dtFilter]\n",
    "#dfannRet.head(10)\n",
    "\n",
    "dfopti = pd.merge(dfannRet,dfval,on='STOCK_TIKR')\n",
    "#dfopti\n",
    "dfopti = dfopti.groupby(['STOCK_TIKR','Date']).mean().reset_index()\n",
    "dfopti.rename(columns = {'Close':'Annual_Ret'}, inplace = True)\n",
    "dfopti = dfopti[['STOCK_TIKR','Date','Annual_Ret']]\n",
    "dfopti.head()\n",
    "dflstRet = dfopti.groupby('STOCK_TIKR')['Annual_Ret'].apply(list).reset_index()\n",
    "lstRet = list(dflstRet.Annual_Ret)\n",
    "stock_list_ret = list(dflstRet.STOCK_TIKR.unique())\n",
    "lstRet\n",
    "#tock_list_ret\n",
    "#flstRet\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In below code with using cvxopt library we are implementing Modern portfolio theory to assign the weights.\n",
    "- Our optimization is subject to Maximizing the returns, with constraints of:\n",
    "- All weights equals to 1\n",
    "- All weights should be positive (No short positions allowed)\n",
    "- We are giving the range of returns between 5 to 10 percent. For each of this return, our function will calculate the weights of all the stocks.\n",
    "- For each return, we are also calculating Sharpe ration.\n",
    "- The return having the highest Sharpe ratio,we will take those weights into consideration for our portfolio stocks."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Returns are [[ -5.3636  28.5495  -6.7943  34.0532 -35.8386   6.4301 -22.0886  -5.3086\n",
      "  -28.9084 -22.4708 -44.6541  -4.3254 -12.7481 -12.5372 -31.044   33.0257\n",
      "  -14.841 ]\n",
      " [ 25.7132  21.2121  23.6301  33.2388  57.5832 -17.8742  24.6235  27.2781\n",
      "  114.5735  19.5107  42.0455   4.4133  82.6336  78.0855  36.5231  15.6572\n",
      "   34.4398]\n",
      " [ 18.8805  23.6842  21.8639  18.4949  11.3067  56.3492  27.4924  30.0703\n",
      "  -58.4208  44.8819  14.6667  21.6495 -16.162   -9.9591  11.5894  31.4364\n",
      "   28.0864]\n",
      " [ 12.0641 -13.5638 -10.8134  -0.2939   4.3234  -4.3733   7.109    3.3712\n",
      "   -2.9216 -17.029   -5.2326   7.2034 -13.2987 -20.7576  -5.1261  -8.6839\n",
      "  -12.0482]]\n",
      "returns shape 4\n",
      "i------ 0\n",
      "sharpe 4 [[-1.02212699  3.96284407 -1.23242914  4.77184664 -5.50172316  0.71145836\n",
      "  -3.4805764  -1.0140424  -4.48303579 -3.53675693 -6.79753546 -0.86951938\n",
      "  -2.10759304 -2.07659232 -4.79695296  4.62081186 -2.41523362]\n",
      " [ 3.54592926  2.88430136  3.23972921  4.65213596  8.23057996 -2.86109125\n",
      "   3.38575155  3.77595781 16.60772613  2.63420834  5.94665473  0.4150039\n",
      "  11.91280066 11.24426411  5.1349034   2.06777277  4.82867394]\n",
      " [ 2.54157367  3.2476815   2.98011107  2.48489337  1.42828194  8.04919123\n",
      "   3.80745831  4.18639025 -8.82113699  6.36358423  1.92217671  2.94859588\n",
      "  -2.6094107  -1.69763098  1.46983672  4.38719669  3.89477184]\n",
      " [ 1.53961405 -2.22749481 -1.82320667 -0.27691915  0.40178928 -0.87656032\n",
      "   0.81125156  0.26182303 -0.66317132 -2.73685319 -1.00287097  0.82512765\n",
      "  -2.1885271  -3.2849294  -0.98721627 -1.51018616 -2.00471299]]\n",
      "i------ 1\n",
      "sharpe 4 [[-1.02212699  3.96284407 -1.23242915  4.77184665 -5.50172316  0.71145836\n",
      "  -3.48057641 -1.0140424  -4.4830358  -3.53675694 -6.79753547 -0.86951938\n",
      "  -2.10759304 -2.07659232 -4.79695296  4.62081186 -2.41523363]\n",
      " [ 3.54592927  2.88430137  3.23972921  4.65213596  8.23057997 -2.86109125\n",
      "   3.38575155  3.77595782 16.60772615  2.63420834  5.94665474  0.4150039\n",
      "  11.91280068 11.24426413  5.1349034   2.06777277  4.82867394]\n",
      " [ 2.54157367  3.2476815   2.98011107  2.48489337  1.42828194  8.04919123\n",
      "   3.80745831  4.18639025 -8.821137    6.36358424  1.92217671  2.94859588\n",
      "  -2.60941071 -1.69763098  1.46983672  4.3871967   3.89477185]\n",
      " [ 1.53961405 -2.22749482 -1.82320667 -0.27691915  0.40178928 -0.87656032\n",
      "   0.81125156  0.26182303 -0.66317132 -2.7368532  -1.00287097  0.82512765\n",
      "  -2.18852711 -3.2849294  -0.98721627 -1.51018616 -2.004713  ]]\n",
      "local wts in if [-3.5339595083249276e-11, 1.1926980171504595e-11, -1.0585798835094264e-11, 0.33756569555223115, -9.998582899196852e-12, -2.6220338762455612e-11, 1.030538453256632e-12, 1.504627210796249e-11, 0.01528146966727263, -1.6183057206529916e-11, 9.333381004057725e-12, 0.6471528349056647, -5.3629631406393635e-12, -9.996982340746577e-12, -1.0360606559910664e-11, -3.1911094780137004e-11, -6.546409711711724e-12]\n",
      "data row in if [-3.5339595083249276e-11, 1.1926980171504595e-11, -1.0585798835094264e-11, 0.33756569555223115, -9.998582899196852e-12, -2.6220338762455612e-11, 1.030538453256632e-12, 1.504627210796249e-11, 0.01528146966727263, -1.6183057206529916e-11, 9.333381004057725e-12, 0.6471528349056647, -5.3629631406393635e-12, -9.996982340746577e-12, -1.0360606559910664e-11, -3.1911094780137004e-11, -6.546409711711724e-12, 1.2238039288504778]\n",
      "i------ 2\n",
      "sharpe 4 [[-1.02212699  3.96284407 -1.23242915  4.77184665 -5.50172317  0.71145836\n",
      "  -3.48057641 -1.0140424  -4.4830358  -3.53675694 -6.79753547 -0.86951938\n",
      "  -2.10759304 -2.07659233 -4.79695297  4.62081186 -2.41523363]\n",
      " [ 3.54592927  2.88430137  3.23972921  4.65213596  8.23057997 -2.86109125\n",
      "   3.38575155  3.77595782 16.60772616  2.63420834  5.94665474  0.4150039\n",
      "  11.91280068 11.24426413  5.1349034   2.06777278  4.82867395]\n",
      " [ 2.54157367  3.24768151  2.98011107  2.48489337  1.42828194  8.04919124\n",
      "   3.80745831  4.18639025 -8.82113701  6.36358424  1.92217671  2.94859588\n",
      "  -2.60941071 -1.69763098  1.46983672  4.3871967   3.89477185]\n",
      " [ 1.53961405 -2.22749482 -1.82320667 -0.27691915  0.40178928 -0.87656032\n",
      "   0.81125156  0.26182303 -0.66317132 -2.7368532  -1.00287097  0.82512765\n",
      "  -2.18852711 -3.2849294  -0.98721627 -1.51018616 -2.004713  ]]\n",
      "local wts in if [-5.5406886711416283e-11, -2.8265974533421295e-11, -2.749711049732422e-11, 0.3375656955784705, -2.9350753194011e-11, -4.713491734998939e-11, -2.686702263218094e-11, -7.839647499980903e-12, 0.015281469732466278, -3.658569989846753e-11, -1.4191718859897552e-11, 0.647152835137562, -3.2729840282954084e-11, -3.4712789309743406e-11, -2.745950359272187e-11, -5.287881676173297e-11, -2.7578118865040862e-11]\n",
      "data row in if [-5.5406886711416283e-11, -2.8265974533421295e-11, -2.749711049732422e-11, 0.3375656955784705, -2.9350753194011e-11, -4.713491734998939e-11, -2.686702263218094e-11, -7.839647499980903e-12, 0.015281469732466278, -3.658569989846753e-11, -1.4191718859897552e-11, 0.647152835137562, -3.2729840282954084e-11, -3.4712789309743406e-11, -2.745950359272187e-11, -5.287881676173297e-11, -2.7578118865040862e-11, 1.223803929482594]\n",
      "i------ 3\n",
      "sharpe 4 [[-1.02212699  3.96284409 -1.23242915  4.77184667 -5.50172318  0.71145836\n",
      "  -3.48057642 -1.01404241 -4.48303582 -3.53675695 -6.7975355  -0.86951939\n",
      "  -2.10759305 -2.07659233 -4.79695298  4.62081188 -2.41523364]\n",
      " [ 3.54592928  2.88430138  3.23972922  4.65213598  8.23058    -2.86109126\n",
      "   3.38575156  3.77595783 16.60772622  2.63420835  5.94665476  0.4150039\n",
      "  11.91280072 11.24426417  5.13490342  2.06777278  4.82867396]\n",
      " [ 2.54157368  3.24768152  2.98011108  2.48489338  1.42828195  8.04919127\n",
      "   3.80745832  4.18639027 -8.82113704  6.36358426  1.92217672  2.94859589\n",
      "  -2.60941072 -1.69763099  1.46983672  4.38719671  3.89477186]\n",
      " [ 1.53961406 -2.22749482 -1.82320667 -0.27691916  0.40178928 -0.87656033\n",
      "   0.81125156  0.26182303 -0.66317133 -2.73685321 -1.00287098  0.82512765\n",
      "  -2.18852712 -3.28492941 -0.98721628 -1.51018616 -2.004713  ]]\n",
      "local wts in if [3.4057443133114767e-10, -1.4283983498867704e-10, -1.4494115772285471e-10, 0.3375656956155657, -1.9800408034900316e-10, -2.2445255962613503e-10, -1.9514249078734728e-10, -1.3559744683133954e-10, 0.015281470140201833, -2.0365722060017293e-10, -1.4247990374754906e-10, 0.64715283621876, -1.9066438890523466e-10, -1.9320091216646614e-10, -1.632164069340657e-10, -2.1193783669123796e-10, -1.689677940916426e-10]\n",
      "data row in if [3.4057443133114767e-10, -1.4283983498867704e-10, -1.4494115772285471e-10, 0.3375656956155657, -1.9800408034900316e-10, -2.2445255962613503e-10, -1.9514249078734728e-10, -1.3559744683133954e-10, 0.015281470140201833, -2.0365722060017293e-10, -1.4247990374754906e-10, 0.64715283621876, -1.9066438890523466e-10, -1.9320091216646614e-10, -1.632164069340657e-10, -2.1193783669123796e-10, -1.689677940916426e-10, 1.2238039335677535]\n",
      "i------ 4\n",
      "sharpe 4 [[-1.00864315  3.91056648 -1.21617102  4.70889674 -5.42914477  0.70207284\n",
      "  -3.43466086 -1.00066522 -4.42389587 -3.49010026 -6.70786281 -0.85804874\n",
      "  -2.0797898  -2.04919805 -4.73367186  4.5598544  -2.38337201]\n",
      " [ 3.49915159  2.84625184  3.1969909   4.59076527  8.12200267 -2.82334791\n",
      "   3.34108693  3.72614562 16.38863806  2.59945803  5.86820684  0.4095292\n",
      "  11.75564775 11.09593049  5.06716408  2.04049485  4.76497438]\n",
      " [ 2.50804539  3.20483829  2.94079763  2.45211281  1.40944013  7.94300681\n",
      "   3.75723056  4.13116365 -8.70476911  6.27963623  1.89681948  2.90969819\n",
      "  -2.57498752 -1.67523594  1.45044672  4.32932107  3.84339226]\n",
      " [ 1.51930356 -2.19810984 -1.79915504 -0.27326605  0.3964889  -0.86499679\n",
      "   0.80054958  0.25836907 -0.65442281 -2.7007488  -0.98964116  0.81424262\n",
      "  -2.15965619 -3.24159482 -0.97419298 -1.49026388 -1.97826695]]\n",
      "i------ 5\n",
      "sharpe 4 [[-0.97139961  3.76617115 -1.17126463  4.53502355 -5.22867685  0.67614922\n",
      "  -3.30783806 -0.96371625 -4.26054616 -3.3612304  -6.46017899 -0.8263658\n",
      "  -2.00299481 -1.97353264 -4.55888386  4.3914845  -2.29536743]\n",
      " [ 3.36994751  2.7411557   3.07894393  4.42125401  7.82210258 -2.71909748\n",
      "   3.21771929  3.58855992 15.78349741  2.5034746   5.65152681  0.39440757\n",
      "  11.32157749 10.6862199   4.88006207  1.96515079  4.58903055]\n",
      " [ 2.41543732  3.08650156  2.83221044  2.36157001  1.3573974   7.64971603\n",
      "   3.61849707  3.97862291 -8.38335072  6.04776442  1.82678055  2.80225932\n",
      "  -2.47990765 -1.61337886  1.39688985  4.16946348  3.7014773 ]\n",
      " [ 1.46320419 -2.11694595 -1.73272232 -0.26317587  0.38184878 -0.83305731\n",
      "   0.77098977  0.24882895 -0.63025864 -2.60102527 -0.95309925  0.7841772\n",
      "  -2.07991218 -3.12190087 -0.93822148 -1.43523677 -1.90522062]]\n",
      "i------ 6\n",
      "sharpe 4 [[-0.90666081  3.51517516 -1.09320585  4.23278749 -4.88021236  0.63108735\n",
      "  -3.08738762 -0.89948951 -3.97660261 -3.13722163 -6.02964119 -0.77129276\n",
      "  -1.86950548 -1.84200681 -4.25505763  4.09881459 -2.14239296]\n",
      " [ 3.1453578   2.55847173  2.87374811  4.12660011  7.30079957 -2.53788358\n",
      "   3.00327481  3.34940081 14.73160826  2.33663086  5.27488154  0.36812233\n",
      "  10.56705242  9.97403816  4.55483097  1.83418357  4.2831952 ]\n",
      " [ 2.25446081  2.88080206  2.64345814  2.20418348  1.26693383  7.1399017\n",
      "   3.3773428   3.7134681  -7.8246434   5.64471194  1.705035    2.61550311\n",
      "  -2.31463453 -1.50585543  1.3037943   3.89159013  3.45479283]\n",
      " [ 1.36568913 -1.97586236 -1.61724526 -0.24563655  0.35640052 -0.77753831\n",
      "   0.71960725  0.23224578 -0.58825513 -2.42768027 -0.88958008  0.73191581\n",
      "  -1.9412967  -2.91384219 -0.87569383 -1.3395856  -1.77824744]]\n",
      "optimal_sigmas 7 [6.803068589300428, 6.8030685819449905, 6.8030685784310885, 6.803068555721877, 6.894013984363191, 7.158331076247693, 7.669461335645895]\n",
      "weights 7 [<17x1 matrix, tc='d'>, <17x1 matrix, tc='d'>, <17x1 matrix, tc='d'>, <17x1 matrix, tc='d'>, <17x1 matrix, tc='d'>, <17x1 matrix, tc='d'>, <17x1 matrix, tc='d'>]\n",
      "sharpe 4 [[-0.90666081  3.51517516 -1.09320585  4.23278749 -4.88021236  0.63108735\n",
      "  -3.08738762 -0.89948951 -3.97660261 -3.13722163 -6.02964119 -0.77129276\n",
      "  -1.86950548 -1.84200681 -4.25505763  4.09881459 -2.14239296]\n",
      " [ 3.1453578   2.55847173  2.87374811  4.12660011  7.30079957 -2.53788358\n",
      "   3.00327481  3.34940081 14.73160826  2.33663086  5.27488154  0.36812233\n",
      "  10.56705242  9.97403816  4.55483097  1.83418357  4.2831952 ]\n",
      " [ 2.25446081  2.88080206  2.64345814  2.20418348  1.26693383  7.1399017\n",
      "   3.3773428   3.7134681  -7.8246434   5.64471194  1.705035    2.61550311\n",
      "  -2.31463453 -1.50585543  1.3037943   3.89159013  3.45479283]\n",
      " [ 1.36568913 -1.97586236 -1.61724526 -0.24563655  0.35640052 -0.77753831\n",
      "   0.71960725  0.23224578 -0.58825513 -2.42768027 -0.88958008  0.73191581\n",
      "  -1.9412967  -2.91384219 -0.87569383 -1.3395856  -1.77824744]]\n",
      "df to save********* df_weight_valport_str_2018\n",
      "Data has been loaded to df_weight_valport_str_2018 table\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Import the necessary packages\n",
    "import numpy as np\n",
    "from cvxopt import matrix\n",
    "from cvxopt import solvers\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn\n",
    "from pandas.core.common import flatten\n",
    "\n",
    "\n",
    "\n",
    "def calculate_MPT(returns,r_min):\n",
    "    # calculation of P matrix in the quadratic equation 1/2 xt P x\n",
    "    cov = np.matrix(np.cov(returns.T))\n",
    "    # number of stocks or assessts\n",
    "    N = returns.shape[1]\n",
    "    # R-bar is the average returns from data. Would be compared to the minimum returns\n",
    "    rbar = np.matrix(returns.mean(0))\n",
    "\n",
    "    # define list of optimal / desired mus for which we'd like to find the optimal sigmas\n",
    "    # This is the minimum returns plus accumulation of returns over 5 years. you can\n",
    "    # also make all 5 years minimum returns equal to 10\n",
    "    optimal_mus = []\n",
    "    for i in range(N):\n",
    "        optimal_mus.append(r_min)\n",
    "        r_min += (rbar.mean() / 100)\n",
    "    \n",
    "    # calculate average minimum expected portfolio returns \n",
    "    mu = np.array(optimal_mus).mean()    \n",
    "\n",
    "    # constraint matrices for quadratic programming. Here I used cvxopt package instead of quadprog that seems to be easier to use\n",
    "    # parameters of cvxopt are similar to quadprog    \n",
    "    P = matrix(cov)\n",
    "    q = matrix(np.zeros((N, 1)))\n",
    "    G = matrix(np.concatenate((-np.array(rbar), -np.identity(N)), 0))\n",
    "    h = matrix(np.concatenate((-np.ones((1,1))*mu, np.zeros((N,1))),0))\n",
    "    A = matrix(1.0, (1,N))\n",
    "    b = matrix(1.0)\n",
    "    \n",
    "    # hide optimization\n",
    "    solvers.options['show_progress'] = False\n",
    "    \n",
    "    # calculate portfolio weights, every weight vector is of size Nx1\n",
    "    # find optimal weights with qp(P, q, G, h, A, b)\n",
    "    optimal_weights = solvers.qp(P, q, G, h, A, b)\n",
    "    w = optimal_weights['x']\n",
    "    \n",
    "    # find optimal sigma\n",
    "    # \\sigma = w^T * Cov * w\n",
    "    #optimal_sigmas = [np.sqrt(np.matrix(w).T * cov.T.dot(np.matrix(w)))[0,0] for w in optimal_weights]\n",
    "    optimal_sigma = np.sqrt(np.matrix(w).T * cov.T.dot(np.matrix(w)))\n",
    "    \n",
    "    return w, optimal_sigma.item(0), mu\n",
    "\n",
    "# print optimum weights\n",
    "\n",
    "\n",
    "def main():\n",
    "    # define returns, returns are a matrix TxN. N is the number of assessts/stocks,\n",
    "   # T number of years, time in time series\n",
    "\n",
    "    returns = np.array(lstRet)\n",
    "    returns = returns.T\n",
    "    print(\"Returns are\",returns)\n",
    "    print(\"returns shape\", returns.shape[0])\n",
    "    minReturns = [8,9,10,11,12,13,14]\n",
    "    mus = []\n",
    "    optimal_sigmas = []\n",
    "    w = []\n",
    "    temp = 0.0\n",
    "    rfrate = 1.59\n",
    "    columns_port = stock_list_ret.copy()\n",
    "    columns_port.append('Sharpe_ratio')\n",
    "    df_weight_valport_str = \"df_weight_valport_str_\" + str(curr_year)\n",
    "    df_wt_valport = pd.DataFrame()\n",
    "#     print(\"data frame for port\",df_wt_valport)\n",
    "    for i in range(len(minReturns)):\n",
    "        print(\"i------\",i)\n",
    "        weights, optimal_sig, mu =calculate_MPT(returns,minReturns[i])\n",
    "        mus.append(mu)\n",
    "        optimal_sigmas.append(optimal_sig)\n",
    "        sharpe = (returns - rfrate) / optimal_sig\n",
    "        print(\"sharpe\", len(sharpe),sharpe)\n",
    "        w.append(weights)\n",
    "#         print(weights)\n",
    "        mean_sharpe = sharpe.mean()\n",
    "#         print(\"Sha\",sharpe.mean())\n",
    "        if (temp == 0.0):\n",
    "            temp = mean_sharpe\n",
    "#             local_wts = np.array(weights)\n",
    "            local_wts = list(flatten(weights))\n",
    "#             print(\"local wts in if\", local_wts) \n",
    "            local_wts.append(mean_sharpe)\n",
    "#             print(\"data row in if\", local_wts)\n",
    "            df_wt_valport = pd.DataFrame(local_wts).T\n",
    "            df_wt_valport.columns=columns_port\n",
    "            \n",
    "#             df_wt_valport\n",
    "#             df_wt_valport.columns =columns_port\n",
    "        elif mean_sharpe>temp:\n",
    "            temp = mean_sharpe\n",
    "            local_wts = list(flatten(weights))\n",
    "            print(\"local wts in if\", local_wts) \n",
    "            local_wts.append(mean_sharpe)\n",
    "            print(\"data row in if\", local_wts)\n",
    "            df_wt_valport = pd.DataFrame(local_wts).T\n",
    "            df_wt_valport.columns=columns_port\n",
    "            df_wt_valport\n",
    "\n",
    "    \n",
    "    print(\"optimal_sigmas\", len(optimal_sigmas),optimal_sigmas)\n",
    "    print(\"weights\", len(w),w)\n",
    "    print(\"sharpe\", len(sharpe),sharpe)\n",
    "    print(\"df to save*********\", df_weight_valport_str)\n",
    "    S2_Construct_Rebalance_Portfolio.saveToSQL(df_weight_valport_str,df_wt_valport,'replace')\n",
    "#    plot Efficient Frontier\n",
    "    plt.plot(optimal_sigmas, [x for x in minReturns],'y-o', color='orange', markersize=8, label='Efficient Frontier')  \n",
    "    plt.xlabel('Expected Volatility (risk)')\n",
    "    plt.ylabel('Expected Return')\n",
    "    plt.title('Efficient Frontier - Value Stock')\n",
    "\n",
    "    \n",
    "    \n",
    "main()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We are storing heighest Sharpe ratio weights and allocating to portfolio.\n",
    "In below code we are calculating Value portfolio returns and comparing with S&P500 returns over different time periods.\n",
    " - **curr_year** and **ref_year** variables defines the time frame"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\Sudip\\Anaconda3\\lib\\site-packages\\ipykernel_launcher.py:33: FutureWarning: Comparing Series of datetimes with 'datetime.date'.  Currently, the\n",
      "'datetime.date' is coerced to a datetime. In the future pandas will\n",
      "not coerce, and a TypeError will be raised. To retain the current\n",
      "behavior, convert the 'datetime.date' to a datetime with\n",
      "'pd.Timestamp'.\n",
      "C:\\Users\\Sudip\\Anaconda3\\lib\\site-packages\\pandas\\core\\frame.py:3781: SettingWithCopyWarning: \n",
      "A value is trying to be set on a copy of a slice from a DataFrame\n",
      "\n",
      "See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy\n",
      "  return super(DataFrame, self).rename(**kwargs)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "stocks inport ['AIR', 'BSET', 'CBT', 'CPS', 'DCO', 'HFC', 'HURC', 'LLL', 'NC', 'NNBR', 'NR', 'REGI', 'REX', 'SANM', 'SEB', 'TSN', 'VSH']\n",
      "ref_year 2015\n",
      "curr_year 2018\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\Sudip\\Anaconda3\\lib\\site-packages\\ipykernel_launcher.py:74: SettingWithCopyWarning: \n",
      "A value is trying to be set on a copy of a slice from a DataFrame.\n",
      "Try using .loc[row_indexer,col_indexer] = value instead\n",
      "\n",
      "See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy\n",
      "C:\\Users\\Sudip\\Anaconda3\\lib\\site-packages\\ipykernel_launcher.py:80: SettingWithCopyWarning: \n",
      "A value is trying to be set on a copy of a slice from a DataFrame.\n",
      "Try using .loc[row_indexer,col_indexer] = value instead\n",
      "\n",
      "See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy\n",
      "C:\\Users\\Sudip\\Anaconda3\\lib\\site-packages\\ipykernel_launcher.py:81: SettingWithCopyWarning: \n",
      "A value is trying to be set on a copy of a slice from a DataFrame.\n",
      "Try using .loc[row_indexer,col_indexer] = value instead\n",
      "\n",
      "See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<matplotlib.axes._subplots.AxesSubplot at 0x1abaf4d0f60>"
      ]
     },
     "execution_count": 58,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "Text(0.5,1,'Performance - Value stock Portfolio')"
      ]
     },
     "execution_count": 58,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>S&amp;P500 returns</th>\n",
       "      <th>Port_ret</th>\n",
       "      <th>year</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>82</th>\n",
       "      <td>-0.73000000</td>\n",
       "      <td>8.25421529</td>\n",
       "      <td>2015</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>83</th>\n",
       "      <td>9.54000000</td>\n",
       "      <td>15.82724651</td>\n",
       "      <td>2016</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>84</th>\n",
       "      <td>19.42000000</td>\n",
       "      <td>19.36100491</td>\n",
       "      <td>2017</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>85</th>\n",
       "      <td>-6.24000000</td>\n",
       "      <td>4.51784414</td>\n",
       "      <td>2018</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "    S&P500 returns    Port_ret  year\n",
       "82     -0.73000000  8.25421529  2015\n",
       "83      9.54000000 15.82724651  2016\n",
       "84     19.42000000 19.36100491  2017\n",
       "85     -6.24000000  4.51784414  2018"
      ]
     },
     "execution_count": 58,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 720x360 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "import pyodbc\n",
    "from sqlalchemy import create_engine\n",
    "from datetime import datetime\n",
    "from datetime import date\n",
    "import datetime\n",
    "\n",
    "pd.options.display.float_format = '{'':'',.8f}'.format\n",
    "engine = create_engine('mysql+pymysql://nativeuser:password@localhost/automatic_portfolio_creation')\n",
    "query_port = \"SELECT * FROM df_weight_valport_str_2019\"\n",
    "port_wt = pd.read_sql(query_port,engine)\n",
    "del port_wt['Sharpe_ratio']\n",
    "port_wt_t = port_wt.T.reset_index()\n",
    "port_wt_t.rename(columns = {'index':'STOCK_TIKR'}, inplace = True)\n",
    "port_wt_t.rename(columns = {0:'weight'}, inplace = True)\n",
    "#print(\"port_wt\")\n",
    "#port_wt_t\n",
    "\n",
    "temp = 0.0\n",
    "list_port_val=[]\n",
    "# df_realtime_price = Construct_Rebalance_Portfolio.dfdataprice.copy()\n",
    "#print(\"real time\")\n",
    "# df_realtime_price\n",
    "\n",
    "# SNP return\n",
    "df_snp = pd.read_csv(r'sp-500-annual-returns.csv')\n",
    "df_snp['date'] = pd.to_datetime(df_snp['date'])\n",
    "curr_year = date.today().year-1\n",
    "ref_year = date.today().year-4\n",
    "#print(\"ref_year\",ref_year)\n",
    "#print(\"curr_year\",curr_year)\n",
    "start_date = datetime.date(ref_year,12,31)\n",
    "end_date = datetime.date(curr_year,12,31)\n",
    "dtFilter = (df_snp['date'] >= start_date) & (df_snp['date'] <= end_date)\n",
    "df_snp_ret = df_snp.loc[dtFilter]\n",
    "df_snp_ret.rename(columns = {'returns':'S&P500 returns'}, inplace = True)\n",
    "#df_snp_ret.head()\n",
    "\n",
    "# Annual return for stocks in the portfolio\n",
    "# df_annual_ret = pd.read_csv(r'hist_annual_ret_all.csv')\n",
    "query_annual = \"SELECT * FROM hist_annual_change\"\n",
    "df_annual_ret = pd.read_sql(query_annual,engine)\n",
    "df_annual_ret['Date'] = pd.to_datetime(df_annual_ret['Date'], format='%Y-%m-%d')\n",
    "df_annual_ret.rename(columns = {'Close':'ANNUAL_RETURN'}, inplace = True)\n",
    "curr_year = date.today().year-1\n",
    "ref_year = date.today().year-4\n",
    "df_annual_ret['year'] = pd.DatetimeIndex(df_annual_ret['Date']).year\n",
    "#print(\"annula retutn table\")\n",
    "# df_annual_ret\n",
    "\n",
    "print(\"stocks inport\", stock_list_ret)\n",
    "print(\"ref_year\",ref_year)\n",
    "print(\"curr_year\",curr_year)\n",
    "filter_1 = (df_annual_ret['year'] >= ref_year) & (df_annual_ret['year'] <= curr_year) & (df_annual_ret['STOCK_TIKR'].isin(stock_list_ret))\n",
    "df_portfolio_stk_rt = df_annual_ret.loc[filter_1]\n",
    "#print(\"df_portfolio_stk_rt\")\n",
    "#df_portfolio_stk_rt.head()\n",
    "\n",
    "new_yrlist = list(range(ref_year,curr_year+1))\n",
    "#print(\"new_yrlist\",new_yrlist)\n",
    "valu_list = []\n",
    "\n",
    "# port_wt.drop('Sharpe_ratio', axis=1, inplace=True)\n",
    "\n",
    "df_port = pd.merge(port_wt_t,df_portfolio_stk_rt, on='STOCK_TIKR')\n",
    "#print(\"Df_oport\")\n",
    "#df_port.head()\n",
    "\n",
    "for each_yr in new_yrlist:\n",
    "    year_wise = df_port.loc[(df_port['year'] == each_yr)]\n",
    "    i=0\n",
    "    #print(year_wise)\n",
    "    for each in stock_list_ret:\n",
    "        if (i<1):\n",
    "            year_wise['prod_wt_ret'] = year_wise.weight*year_wise.ANNUAL_RETURN\n",
    "            result = year_wise.prod_wt_ret.sum()\n",
    "            result= result*100\n",
    "            list_port_val.append(result.tolist())\n",
    "            i=i+1\n",
    "#print(\"length of\",len(list_port_val))\n",
    "df_snp_ret['Port_ret'] = list_port_val\n",
    "df_snp_ret['year'] = pd.DatetimeIndex(df_snp_ret['date']).year\n",
    "del df_snp_ret['date']\n",
    "df_snp_ret.to_csv(\"snp_port_val_ret_comparison.csv\")\n",
    "df_snp_ret.set_index('year').plot(figsize=(10,5), grid=True)\n",
    "plt.title('Performance - Value stock Portfolio')\n",
    "df_snp_ret"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "All above operations were for the Value portfolio. We will do same operation to growth portfolio as below:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\Sudip\\Anaconda3\\lib\\site-packages\\ipykernel_launcher.py:19: FutureWarning: Comparing Series of datetimes with 'datetime.date'.  Currently, the\n",
      "'datetime.date' is coerced to a datetime. In the future pandas will\n",
      "not coerce, and a TypeError will be raised. To retain the current\n",
      "behavior, convert the 'datetime.date' to a datetime with\n",
      "'pd.Timestamp'.\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>STOCK_TIKR</th>\n",
       "      <th>Annual_Ret</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>AAPL</td>\n",
       "      <td>12.74565000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>ADI</td>\n",
       "      <td>13.94460000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>CHRW</td>\n",
       "      <td>6.32962500</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>CMI</td>\n",
       "      <td>8.86322500</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>CSCO</td>\n",
       "      <td>11.77190000</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  STOCK_TIKR  Annual_Ret\n",
       "0       AAPL 12.74565000\n",
       "1        ADI 13.94460000\n",
       "6       CHRW  6.32962500\n",
       "7        CMI  8.86322500\n",
       "8       CSCO 11.77190000"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# We will look past 5-years returns and select positive return stocks for optimizatin\n",
    "# To avoid imbalance weightage\n",
    "\n",
    "engine = create_engine('mysql+pymysql://nativeuser:password@localhost/automatic_portfolio_creation')\n",
    "query_ann_ret = \"SELECT * FROM hist_annual_change\"\n",
    "\n",
    "curr_year = date.today().year \n",
    "ref_year = date.today().year - 5\n",
    "start_date = datetime.date(ref_year,12,31)\n",
    "end_date = datetime.date(curr_year,12,31)\n",
    "dfvalg = S2_Construct_Rebalance_Portfolio.dflookupG.copy()\n",
    "dfvalg.rename(columns = {'symbol':'STOCK_TIKR'}, inplace = True)\n",
    "#dfvalg.head()\n",
    "\n",
    "dfannRet =pd.read_sql(query_ann_ret,engine)\n",
    "dfannRet['Close'] = dfannRet['Close']*100\n",
    "dfannRet['Close'] = dfannRet['Close'].round(4)\n",
    "dfannRet['Date'] = pd.to_datetime(dfannRet['Date'])\n",
    "dtFilter = (dfannRet['Date'] > start_date) & (dfannRet['Date'] <= end_date)\n",
    "dfannRet = dfannRet.loc[dtFilter]\n",
    "#dfannRet.head(10)\n",
    "\n",
    "dfvaloptig = pd.merge(dfannRet,dfvalg,on='STOCK_TIKR')\n",
    "dfvaloptig = dfvaloptig.groupby(['STOCK_TIKR']).mean().reset_index()\n",
    "dfvaloptig = dfvaloptig[(dfvaloptig['Close'] >5 ) & (dfvaloptig['Close'] < 25)]\n",
    "dfvaloptig.rename(columns = {'Close':'Annual_Ret'}, inplace = True)\n",
    "dfvaloptig = dfvaloptig[['STOCK_TIKR','Annual_Ret']]\n",
    "#dfvaloptig.head()\n",
    "dfvaloptig.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>STOCK_TIKR</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>AAPL</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>ADI</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>CHRW</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>CMI</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>CSCO</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  STOCK_TIKR\n",
       "0       AAPL\n",
       "1        ADI\n",
       "2       CHRW\n",
       "3        CMI\n",
       "4       CSCO"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dflookupoptig = pd.DataFrame()\n",
    "dflookupoptig['STOCK_TIKR'] = dfvaloptig['STOCK_TIKR'].values\n",
    "dflookupoptig.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\Sudip\\Anaconda3\\lib\\site-packages\\ipykernel_launcher.py:26: FutureWarning: Comparing Series of datetimes with 'datetime.date'.  Currently, the\n",
      "'datetime.date' is coerced to a datetime. In the future pandas will\n",
      "not coerce, and a TypeError will be raised. To retain the current\n",
      "behavior, convert the 'datetime.date' to a datetime with\n",
      "'pd.Timestamp'.\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>STOCK_TIKR</th>\n",
       "      <th>Date</th>\n",
       "      <th>Annual_Ret</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>AAPL</td>\n",
       "      <td>2015-12-31</td>\n",
       "      <td>-4.63850000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>AAPL</td>\n",
       "      <td>2016-12-31</td>\n",
       "      <td>10.03230000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>AAPL</td>\n",
       "      <td>2017-12-31</td>\n",
       "      <td>46.11470000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>AAPL</td>\n",
       "      <td>2018-12-31</td>\n",
       "      <td>-0.52590000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>ADI</td>\n",
       "      <td>2015-12-31</td>\n",
       "      <td>-0.36020000</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  STOCK_TIKR       Date  Annual_Ret\n",
       "0       AAPL 2015-12-31 -4.63850000\n",
       "1       AAPL 2016-12-31 10.03230000\n",
       "2       AAPL 2017-12-31 46.11470000\n",
       "3       AAPL 2018-12-31 -0.52590000\n",
       "4        ADI 2015-12-31 -0.36020000"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "[[-4.6385, 10.0323, 46.1147, -0.5259],\n",
       " [-0.3602, 31.2726, 22.5971, 2.2689],\n",
       " [-17.1852, 18.1232, 21.608, 2.7725],\n",
       " [-38.954, 55.2892, 29.2456, -10.1279],\n",
       " [-2.3728, 11.2871, 26.7373, 11.436],\n",
       " [13.9765, -6.6478, 26.7535, 12.757],\n",
       " [46.6118, 1.856, 32.9295, -4.4105],\n",
       " [-13.4503, 58.9013, -9.6506, -4.072],\n",
       " [24.2846, 14.2961, 21.5851, 7.8929],\n",
       " [-5.0703, 5.283, 27.2677, 10.8969],\n",
       " [-2.1331, 32.1321, 36.2486, -6.7186],\n",
       " [9.4596, -1.2888, 28.6081, -5.6019],\n",
       " [12.9991, 6.0497, 46.5956, 13.9799],\n",
       " [-3.1272, 21.8936, 20.4172, 0.0],\n",
       " [-8.3252, 18.5409, 33.4267, -1.129],\n",
       " [2.0423, 21.0957, 8.9878, 17.257],\n",
       " [-35.9952, 32.9438, 56.8472, 10.611],\n",
       " [14.0865, 5.6357, 17.0582, -5.3782],\n",
       " [-1.4736, 28.9111, 29.238, 2.3896],\n",
       " [2.1502, 7.228, 37.1824, 2.904],\n",
       " [42.8485, -3.38, 34.5287, 0.3917]]"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import pyodbc\n",
    "from sqlalchemy import create_engine\n",
    "from datetime import datetime\n",
    "from datetime import date\n",
    "import datetime\n",
    "\n",
    "\n",
    "engine = create_engine('mysql+pymysql://nativeuser:password@localhost/automatic_portfolio_creation')\n",
    "query_ann_ret = \"SELECT * FROM hist_annual_change\"\n",
    "\n",
    "curr_year = date.today().year \n",
    "ref_year = date.today().year - 5\n",
    "start_date = datetime.date(ref_year,12,31)\n",
    "end_date = datetime.date(curr_year,12,31)\n",
    "dfvalg = dflookupoptig.copy()\n",
    "dfval.rename(columns = {'symbol':'STOCK_TIKR'}, inplace = True)\n",
    "#dfval.head()\n",
    "# query_g = \"SELECT STOCK_TIKR FROM growth_portfolio  where BUY_NOW = 'Yes'\"\n",
    "# dfvalg = pd.read_sql(query_g,engine)\n",
    "\n",
    "\n",
    "dfannRet =pd.read_sql(query_ann_ret,engine)\n",
    "dfannRet['Close'] = dfannRet['Close']*100\n",
    "dfannRet['Close'] = dfannRet['Close'].round(4)\n",
    "dfannRet['Date'] = pd.to_datetime(dfannRet['Date'])\n",
    "dtFilter = (dfannRet['Date'] > start_date) & (dfannRet['Date'] <= end_date)\n",
    "dfannRet = dfannRet.loc[dtFilter]\n",
    "#dfannRet.head(10)\n",
    "\n",
    "dfoptig = pd.merge(dfannRet,dfvalg,on='STOCK_TIKR')\n",
    "#dfoptig.head()\n",
    "dfoptig = dfoptig.groupby(['STOCK_TIKR','Date']).mean().reset_index()\n",
    "# dfvalopti = dfvalopti[(dfvalopti['Close'] > -1) & (dfvalopti['Close'] < 25)]\n",
    "dfoptig.rename(columns = {'Close':'Annual_Ret'}, inplace = True)\n",
    "dfoptig = dfoptig[['STOCK_TIKR','Date','Annual_Ret']]\n",
    "dfoptig.head()\n",
    "dflstRet = dfoptig.groupby('STOCK_TIKR')['Annual_Ret'].apply(list).reset_index()\n",
    "lstRetg = list(dflstRet.Annual_Ret)\n",
    "# #lstRet = [ round(elem, 4) for elem in lstRet ]\n",
    "lstRetg\n",
    "stock_list_growth_ret = list(dflstRet.STOCK_TIKR.unique())\n",
    "# #get_data_In_Csv_annual('bal_sheet_annual',list_col_balance_sheet,dfStockDec['ticker'])\n",
    "#stock_list_growth_ret"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Returns are [[ -4.6385  -0.3602 -17.1852 -38.954   -2.3728  13.9765  46.6118 -13.4503\n",
      "   24.2846  -5.0703  -2.1331   9.4596  12.9991  -3.1272  -8.3252   2.0423\n",
      "  -35.9952  14.0865  -1.4736   2.1502  42.8485]\n",
      " [ 10.0323  31.2726  18.1232  55.2892  11.2871  -6.6478   1.856   58.9013\n",
      "   14.2961   5.283   32.1321  -1.2888   6.0497  21.8936  18.5409  21.0957\n",
      "   32.9438   5.6357  28.9111   7.228   -3.38  ]\n",
      " [ 46.1147  22.5971  21.608   29.2456  26.7373  26.7535  32.9295  -9.6506\n",
      "   21.5851  27.2677  36.2486  28.6081  46.5956  20.4172  33.4267   8.9878\n",
      "   56.8472  17.0582  29.238   37.1824  34.5287]\n",
      " [ -0.5259   2.2689   2.7725 -10.1279  11.436   12.757   -4.4105  -4.072\n",
      "    7.8929  10.8969  -6.7186  -5.6019  13.9799   0.      -1.129   17.257\n",
      "   10.611   -5.3782   2.3896   2.904    0.3917]]\n",
      "returns shape 4\n",
      "[ 3.12e-10]\n",
      "[ 8.46e-10]\n",
      "[ 7.18e-10]\n",
      "[-1.72e-11]\n",
      "[ 1.57e-09]\n",
      "[ 2.56e-08]\n",
      "[ 5.29e-08]\n",
      "[ 1.47e-09]\n",
      "[ 2.86e-08]\n",
      "[ 1.69e-09]\n",
      "[ 2.65e-10]\n",
      "[ 1.43e-09]\n",
      "[ 1.03e-09]\n",
      "[ 1.00e-09]\n",
      "[ 4.32e-10]\n",
      "[ 7.36e-01]\n",
      "[ 6.82e-12]\n",
      "[ 3.78e-09]\n",
      "[ 5.99e-10]\n",
      "[ 7.61e-10]\n",
      "[ 2.64e-01]\n",
      "\n",
      "Sharpe Ratio 7.6266173235652275\n",
      "[-1.27e-10]\n",
      "[ 3.83e-10]\n",
      "[ 1.53e-10]\n",
      "[-3.02e-10]\n",
      "[ 1.00e-09]\n",
      "[ 1.64e-08]\n",
      "[ 4.93e-08]\n",
      "[ 6.13e-10]\n",
      "[ 1.97e-08]\n",
      "[ 9.10e-10]\n",
      "[-9.82e-11]\n",
      "[ 5.75e-10]\n",
      "[ 2.52e-10]\n",
      "[ 4.72e-10]\n",
      "[-2.06e-11]\n",
      "[ 7.36e-01]\n",
      "[-2.71e-10]\n",
      "[ 2.61e-09]\n",
      "[ 8.89e-11]\n",
      "[ 2.15e-10]\n",
      "[ 2.64e-01]\n",
      "\n",
      "Sharpe Ratio 7.626618007621035\n",
      "local wts in if [-1.268166957614022e-10, 3.829115093434179e-10, 1.5265441338567487e-10, -3.0205656125589113e-10, 9.99524035506013e-10, 1.64027163562778e-08, 4.9338403073072124e-08, 6.13451023091816e-10, 1.9675053151332577e-08, 9.095234357675706e-10, -9.815218643165901e-11, 5.748971738115015e-10, 2.521351128646282e-10, 4.716414082980364e-10, -2.0572619063984685e-11, 0.7361936762695616, -2.7086276932421124e-10, 2.60739487177197e-09, 8.886883996735149e-11, 2.1516000496848835e-10, 0.263806231864565]\n",
      "data row in if [-1.268166957614022e-10, 3.829115093434179e-10, 1.5265441338567487e-10, -3.0205656125589113e-10, 9.99524035506013e-10, 1.64027163562778e-08, 4.9338403073072124e-08, 6.13451023091816e-10, 1.9675053151332577e-08, 9.095234357675706e-10, -9.815218643165901e-11, 5.748971738115015e-10, 2.521351128646282e-10, 4.716414082980364e-10, -2.0572619063984685e-11, 0.7361936762695616, -2.7086276932421124e-10, 2.60739487177197e-09, 8.886883996735149e-11, 2.1516000496848835e-10, 0.263806231864565, 7.626618007621035]\n",
      "[-6.31e-12]\n",
      "[-4.12e-14]\n",
      "[-4.57e-12]\n",
      "[-5.04e-12]\n",
      "[ 1.36e-12]\n",
      "[ 1.16e-10]\n",
      "[ 1.36e-10]\n",
      "[-2.89e-12]\n",
      "[ 1.56e-10]\n",
      "[-1.20e-12]\n",
      "[-5.64e-12]\n",
      "[ 5.55e-12]\n",
      "[ 2.41e-11]\n",
      "[-5.33e-12]\n",
      "[-6.11e-12]\n",
      "[ 7.36e-01]\n",
      "[-5.70e-12]\n",
      "[ 3.91e-11]\n",
      "[-3.25e-13]\n",
      "[-5.74e-12]\n",
      "[ 2.64e-01]\n",
      "\n",
      "Sharpe Ratio 7.626618418534693\n",
      "local wts in if [-6.305048930795854e-12, -4.122091297728871e-14, -4.568017403301597e-12, -5.039174098535871e-12, 1.3647305567313227e-12, 1.1561604987199183e-10, 1.3592245433782518e-10, -2.888056395316056e-12, 1.5625762151883927e-10, -1.2048903199836095e-12, -5.642621366545658e-12, 5.553937494639763e-12, 2.407773281194699e-11, -5.3252748909435165e-12, -6.114698996323611e-12, 0.7361936972097486, -5.695869858348319e-12, 3.910254137898334e-11, -3.2502197443084505e-13, -5.741101512719576e-12, 0.26380630236124725]\n",
      "data row in if [-6.305048930795854e-12, -4.122091297728871e-14, -4.568017403301597e-12, -5.039174098535871e-12, 1.3647305567313227e-12, 1.1561604987199183e-10, 1.3592245433782518e-10, -2.888056395316056e-12, 1.5625762151883927e-10, -1.2048903199836095e-12, -5.642621366545658e-12, 5.553937494639763e-12, 2.407773281194699e-11, -5.3252748909435165e-12, -6.114698996323611e-12, 0.7361936972097486, -5.695869858348319e-12, 3.910254137898334e-11, -3.2502197443084505e-13, -5.741101512719576e-12, 0.26380630236124725, 7.626618418534693]\n",
      "[-1.55e-10]\n",
      "[-1.93e-10]\n",
      "[-1.41e-10]\n",
      "[-1.59e-10]\n",
      "[-8.44e-12]\n",
      "[-1.81e-10]\n",
      "[ 2.40e-10]\n",
      "[ 2.87e-11]\n",
      "[ 1.31e-01]\n",
      "[-2.73e-11]\n",
      "[-1.90e-10]\n",
      "[-1.14e-10]\n",
      "[ 3.00e-10]\n",
      "[-1.75e-10]\n",
      "[-1.62e-10]\n",
      "[ 6.61e-01]\n",
      "[-1.59e-10]\n",
      "[-5.58e-11]\n",
      "[-1.59e-10]\n",
      "[-1.17e-10]\n",
      "[ 2.08e-01]\n",
      "\n",
      "Sharpe Ratio 7.057416899702229\n",
      "[ 7.61e-12]\n",
      "[ 8.52e-12]\n",
      "[ 6.73e-12]\n",
      "[ 3.06e-12]\n",
      "[ 2.64e-11]\n",
      "[ 3.39e-09]\n",
      "[ 2.26e-10]\n",
      "[ 4.90e-12]\n",
      "[ 5.62e-01]\n",
      "[ 3.02e-11]\n",
      "[ 5.30e-12]\n",
      "[ 1.03e-11]\n",
      "[ 3.82e-02]\n",
      "[ 8.06e-12]\n",
      "[ 6.70e-12]\n",
      "[ 4.00e-01]\n",
      "[ 5.55e-12]\n",
      "[ 9.26e-12]\n",
      "[ 8.20e-12]\n",
      "[ 1.18e-11]\n",
      "[ 2.44e-08]\n",
      "\n",
      "Sharpe Ratio 4.403519852789093\n",
      "[ 3.98e-10]\n",
      "[ 2.32e-09]\n",
      "[ 4.12e-10]\n",
      "[ 6.40e-10]\n",
      "[ 6.69e-10]\n",
      "[ 3.59e-10]\n",
      "[ 9.71e-10]\n",
      "[ 1.26e-08]\n",
      "[ 6.40e-01]\n",
      "[ 4.18e-10]\n",
      "[ 8.04e-10]\n",
      "[ 2.78e-10]\n",
      "[ 1.22e-01]\n",
      "[ 5.52e-10]\n",
      "[ 4.44e-10]\n",
      "[ 2.38e-01]\n",
      "[ 3.79e-09]\n",
      "[ 3.74e-10]\n",
      "[ 1.68e-09]\n",
      "[ 4.60e-10]\n",
      "[ 8.04e-10]\n",
      "\n",
      "Sharpe Ratio 2.4209897593281817\n",
      "Volatility 0.02152638956304265\n",
      "Average Growth Rate: 0.13758033452380952\n",
      "Sharpe Ratio 2.4209897593281817\n",
      "Data has been loaded to df_weight_growthport_str_2019 table\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Import the necessary packages\n",
    "import numpy as np\n",
    "from cvxopt import matrix\n",
    "from cvxopt import solvers\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn\n",
    "from statistics import mean\n",
    "\n",
    "\n",
    "def calculate_MPT(returns,r_min):\n",
    "    # calculation of P matrix in the quadratic equation 1/2 xt P x\n",
    "    cov = np.matrix(np.cov(returns.T))\n",
    "    # number of stocks or assessts\n",
    "    N = returns.shape[1]\n",
    "    # R-bar is the average returns from data. Would be compared to the minimum returns\n",
    "    rbar = np.matrix(returns.mean(0))\n",
    "\n",
    "    # define list of optimal / desired mus for which we'd like to find the optimal sigmas\n",
    "    # This is the minimum returns plus accumulation of returns over 5 years. you can\n",
    "    # also make all 5 years minimum returns equal to 10\n",
    "    optimal_mus = []\n",
    "    for i in range(N):\n",
    "        optimal_mus.append(r_min)\n",
    "        r_min += (rbar.mean() / 100)\n",
    "    \n",
    "    # calculate average minimum expected portfolio returns \n",
    "    mu = np.array(optimal_mus).mean()    \n",
    "\n",
    "    # constraint matrices for quadratic programming. Here I used cvxopt package instead of quadprog that seems to be easier to use\n",
    "    # parameters of cvxopt are similar to quadprog    \n",
    "    P = matrix(cov)\n",
    "    q = matrix(np.zeros((N, 1)))\n",
    "    G = matrix(np.concatenate((-np.array(rbar), -np.identity(N)), 0))\n",
    "    h = matrix(np.concatenate((-np.ones((1,1))*mu, np.zeros((N,1))),0))\n",
    "    A = matrix(1.0, (1,N))\n",
    "    b = matrix(1.0)\n",
    "    \n",
    "    # hide optimization\n",
    "    solvers.options['show_progress'] = False\n",
    "    \n",
    "    # calculate portfolio weights, every weight vector is of size Nx1\n",
    "    # find optimal weights with qp(P, q, G, h, A, b)\n",
    "    optimal_weights = solvers.qp(P, q, G, h, A, b)\n",
    "    w = optimal_weights['x']\n",
    "    \n",
    "    # find optimal sigma\n",
    "    # \\sigma = w^T * Cov * w\n",
    "    #optimal_sigmas = [np.sqrt(np.matrix(w).T * cov.T.dot(np.matrix(w)))[0,0] for w in optimal_weights]\n",
    "    optimal_sigma = np.sqrt(np.matrix(w).T * cov.T.dot(np.matrix(w)))\n",
    "    \n",
    "    return w, optimal_sigma.item(0), mu\n",
    "\n",
    "# print optimum weights\n",
    "\n",
    "\n",
    "def main():\n",
    "    # define returns, returns are a matrix TxN. N is the number of assessts/stocks,\n",
    "   # T number of years, time in time series\n",
    "\n",
    "    returns = np.array(lstRetg)\n",
    "    returns = returns.T\n",
    "    print(\"Returns are\",returns)\n",
    "    print(\"returns shape\", returns.shape[0])\n",
    "    minReturns = [10, 11, 12, 13, 14, 15]\n",
    "    mus = []\n",
    "    optimal_sigmas = []\n",
    "    w = []\n",
    "    rfrate = 1.59\n",
    "    temp = 0.0\n",
    "    columns_port = stock_list_growth_ret.copy()\n",
    "    columns_port.append('Sharpe_ratio')\n",
    "    df_weight_growthport_str = \"df_weight_growthport_str_\" + str(curr_year)\n",
    "    df_wt_groport = pd.DataFrame()\n",
    "    for i in range(len(minReturns)):\n",
    "        weights, optimal_sig, mu =calculate_MPT(returns,minReturns[i])\n",
    "        mus.append(mu)\n",
    "        optimal_sigmas.append(optimal_sig)\n",
    "        sharpe = (returns-rfrate) / optimal_sig\n",
    "        w.append(weights)\n",
    "        print(weights)\n",
    "#         print(\"Volatility\",mean(optimal_sigmas))\n",
    "#         print(\"Average Growth Rate:\",mean(mus))\n",
    "        print(\"Sharpe Ratio\",sharpe.mean())\n",
    "        mean_sharpe = sharpe.mean()\n",
    "#         print(\"Sha\",sharpe.mean())\n",
    "        if (temp == 0.0):\n",
    "            temp = mean_sharpe\n",
    "#             local_wts = np.array(weights)\n",
    "            local_wts = list(flatten(weights))\n",
    "#             print(\"local wts in if\", local_wts) \n",
    "            local_wts.append(mean_sharpe)\n",
    "#             print(\"data row in if\", local_wts)\n",
    "            df_wt_groport = pd.DataFrame(local_wts).T\n",
    "            df_wt_groport.columns=columns_port\n",
    "        elif mean_sharpe>temp:\n",
    "            temp = mean_sharpe\n",
    "            local_wts = list(flatten(weights))\n",
    "            print(\"local wts in if\", local_wts) \n",
    "            local_wts.append(mean_sharpe)\n",
    "            print(\"data row in if\", local_wts)\n",
    "            df_wt_groport = pd.DataFrame(local_wts).T\n",
    "            df_wt_groport.columns=columns_port\n",
    "    df_wt_groport\n",
    "\n",
    "#    plot Efficient Frontier\n",
    "    plt.plot(optimal_sigmas, [x for x in minReturns],'y-o', color='orange', markersize=8, label='Efficient Frontier')  \n",
    "    plt.xlabel('Expected Volatility (risk)')\n",
    "    plt.ylabel('Expected Return')\n",
    "    plt.title('Efficient Frontier - Growth Stock')\n",
    "    print(\"Volatility\",mean(optimal_sigmas)/100)\n",
    "    print(\"Average Growth Rate:\",mean(mus)/100)\n",
    "    print(\"Sharpe Ratio\",sharpe.mean())\n",
    "    S2_Construct_Rebalance_Portfolio.saveToSQL(df_weight_growthport_str,df_wt_groport,'replace')\n",
    "\n",
    "    \n",
    "    \n",
    "        \n",
    "main()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "real time\n",
      "ref_year 2015\n",
      "curr_year 2018\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\Sudip\\Anaconda3\\lib\\site-packages\\ipykernel_launcher.py:32: FutureWarning: Comparing Series of datetimes with 'datetime.date'.  Currently, the\n",
      "'datetime.date' is coerced to a datetime. In the future pandas will\n",
      "not coerce, and a TypeError will be raised. To retain the current\n",
      "behavior, convert the 'datetime.date' to a datetime with\n",
      "'pd.Timestamp'.\n",
      "C:\\Users\\Sudip\\Anaconda3\\lib\\site-packages\\pandas\\core\\frame.py:3781: SettingWithCopyWarning: \n",
      "A value is trying to be set on a copy of a slice from a DataFrame\n",
      "\n",
      "See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy\n",
      "  return super(DataFrame, self).rename(**kwargs)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "new_yrlist [2015, 2016, 2017, 2018]\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\Sudip\\Anaconda3\\lib\\site-packages\\ipykernel_launcher.py:73: SettingWithCopyWarning: \n",
      "A value is trying to be set on a copy of a slice from a DataFrame.\n",
      "Try using .loc[row_indexer,col_indexer] = value instead\n",
      "\n",
      "See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy\n",
      "C:\\Users\\Sudip\\Anaconda3\\lib\\site-packages\\ipykernel_launcher.py:79: SettingWithCopyWarning: \n",
      "A value is trying to be set on a copy of a slice from a DataFrame.\n",
      "Try using .loc[row_indexer,col_indexer] = value instead\n",
      "\n",
      "See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "SNP Return Vs Portfolio Return\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\Sudip\\Anaconda3\\lib\\site-packages\\ipykernel_launcher.py:80: SettingWithCopyWarning: \n",
      "A value is trying to be set on a copy of a slice from a DataFrame.\n",
      "Try using .loc[row_indexer,col_indexer] = value instead\n",
      "\n",
      "See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "S&P500 returns    5.49750000\n",
       "Port_ret         13.99490218\n",
       "dtype: float64"
      ]
     },
     "execution_count": 57,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>S&amp;P500 returns</th>\n",
       "      <th>Port_ret</th>\n",
       "      <th>year</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>82</th>\n",
       "      <td>-0.73000000</td>\n",
       "      <td>12.80725636</td>\n",
       "      <td>2015</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>83</th>\n",
       "      <td>9.54000000</td>\n",
       "      <td>14.63884818</td>\n",
       "      <td>2016</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>84</th>\n",
       "      <td>19.42000000</td>\n",
       "      <td>15.72565854</td>\n",
       "      <td>2017</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>85</th>\n",
       "      <td>-6.24000000</td>\n",
       "      <td>12.80784562</td>\n",
       "      <td>2018</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "    S&P500 returns    Port_ret  year\n",
       "82     -0.73000000 12.80725636  2015\n",
       "83      9.54000000 14.63884818  2016\n",
       "84     19.42000000 15.72565854  2017\n",
       "85     -6.24000000 12.80784562  2018"
      ]
     },
     "execution_count": 57,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "<matplotlib.axes._subplots.AxesSubplot at 0x1abaf4f1780>"
      ]
     },
     "execution_count": 57,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "Text(0.5,1,'Performance - Growth stock Portfolio')"
      ]
     },
     "execution_count": 57,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 720x360 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "import pyodbc\n",
    "from sqlalchemy import create_engine\n",
    "from datetime import datetime\n",
    "from datetime import date\n",
    "import datetime\n",
    "\n",
    "pd.options.display.float_format = '{'':'',.8f}'.format\n",
    "engine = create_engine('mysql+pymysql://nativeuser:password@localhost/automatic_portfolio_creation')\n",
    "query_port = \"SELECT * FROM df_weight_growthport_str_2019\"\n",
    "port_wt = pd.read_sql(query_port,engine)\n",
    "del port_wt['Sharpe_ratio']\n",
    "port_wt_t = port_wt.T.reset_index()\n",
    "port_wt_t.rename(columns = {'index':'STOCK_TIKR'}, inplace = True)\n",
    "port_wt_t.rename(columns = {0:'weight'}, inplace = True)\n",
    "#port_wt_t\n",
    "\n",
    "temp = 0.0\n",
    "list_port_val=[]\n",
    "# df_realtime_price = Construct_Rebalance_Portfolio.dfdataprice.copy()\n",
    "print(\"real time\")\n",
    "# df_realtime_price\n",
    "\n",
    "# SNP return\n",
    "df_snp = pd.read_csv(r'sp-500-annual-returns.csv')\n",
    "df_snp['date'] = pd.to_datetime(df_snp['date'])\n",
    "curr_year = date.today().year-1\n",
    "ref_year = date.today().year-4\n",
    "print(\"ref_year\",ref_year)\n",
    "print(\"curr_year\",curr_year)\n",
    "start_date = datetime.date(ref_year,12,31)\n",
    "end_date = datetime.date(curr_year,12,31)\n",
    "dtFilter = (df_snp['date'] >= start_date) & (df_snp['date'] <= end_date)\n",
    "df_snp_ret = df_snp.loc[dtFilter]\n",
    "df_snp_ret.rename(columns = {'returns':'S&P500 returns'}, inplace = True)\n",
    "#df_snp_ret.head(10)\n",
    "\n",
    "# Annual return for stocks in the portfolio\n",
    "# df_annual_ret = pd.read_csv(r'hist_annual_ret_all.csv')\n",
    "query_annual = \"SELECT * FROM hist_annual_change\"\n",
    "df_annual_ret = pd.read_sql(query_annual,engine)\n",
    "df_annual_ret['Date'] = pd.to_datetime(df_annual_ret['Date'], format='%Y-%m-%d')\n",
    "df_annual_ret.rename(columns = {'Close':'ANNUAL_RETURN'}, inplace = True)\n",
    "curr_year = date.today().year-1\n",
    "ref_year = date.today().year-4\n",
    "df_annual_ret['year'] = pd.DatetimeIndex(df_annual_ret['Date']).year\n",
    "#print(\"annula retutn table\")\n",
    "# df_annual_ret\n",
    "\n",
    "#print(\"stocks inport\", stock_list_growth_ret)\n",
    "#print(\"ref_year\",ref_year)\n",
    "#print(\"curr_year\",curr_year)\n",
    "filter_1 = (df_annual_ret['year'] >= ref_year) & (df_annual_ret['year'] <= curr_year) & (df_annual_ret['STOCK_TIKR'].isin(stock_list_growth_ret))\n",
    "df_portfolio_stk_rt = df_annual_ret.loc[filter_1]\n",
    "#print(\"df_portfolio_stk_rt\")\n",
    "# df_portfolio_stk_rt.head(10)\n",
    "\n",
    "new_yrlist = list(range(ref_year,curr_year+1))\n",
    "print(\"new_yrlist\",new_yrlist)\n",
    "valu_list = []\n",
    "\n",
    "# port_wt.drop('Sharpe_ratio', axis=1, inplace=True)\n",
    "\n",
    "df_port = pd.merge(port_wt_t,df_portfolio_stk_rt, on='STOCK_TIKR')\n",
    "#print(\"Df_oport\")\n",
    "#df_port\n",
    "\n",
    "for each_yr in new_yrlist:\n",
    "    year_wise = df_port.loc[(df_port['year'] == each_yr)]\n",
    "    i=0\n",
    "    #print(year_wise)\n",
    "    for each in stock_list_growth_ret:\n",
    "        if (i<1):\n",
    "            year_wise['prod_wt_ret'] = year_wise.weight*year_wise.ANNUAL_RETURN\n",
    "            result = year_wise.prod_wt_ret.sum()\n",
    "            result= result*100\n",
    "            list_port_val.append(result.tolist())\n",
    "            i=i+1\n",
    "#print(\"length of\",len(list_port_val))\n",
    "df_snp_ret['Port_ret'] = list_port_val\n",
    "df_snp_ret['year'] = pd.DatetimeIndex(df_snp_ret['date']).year\n",
    "del df_snp_ret['date']\n",
    "print(\"SNP Return Vs Portfolio Return\")\n",
    "df_snp_ret[['S&P500 returns','Port_ret']].mean()\n",
    "df_snp_ret.to_csv(\"snp_port_ret_comparison.csv\")\n",
    "df_snp_ret\n",
    "df_snp_ret.set_index('year').plot(figsize=(10,5), grid=True)\n",
    "plt.title('Performance - Growth stock Portfolio')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
